package com.ruoyi.crm.service.impl;

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.AuditStatus;
import com.ruoyi.common.enums.erp.CrmTaskEnum;
import com.ruoyi.common.enums.flow.FlowTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.flow.FlowDTO;
import com.ruoyi.common.utils.flow.FlowParamsUtils;
import com.ruoyi.crm.domain.*;
import com.ruoyi.crm.mapper.CrmFeeApplyDetailsMapper;
import com.ruoyi.crm.service.ICrmCustomerService;
import com.ruoyi.crm.service.ICrmFeeApplyDetailsService;
import com.ruoyi.crm.service.ICrmOrderService;
import com.ruoyi.crm.utils.ThreadLocalUtils;
import com.warm.flow.core.dto.FlowParams;
import com.warm.flow.core.entity.Instance;
import com.warm.flow.core.enums.SkipType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.crm.mapper.CrmFeeApplyMapper;
import com.ruoyi.crm.service.ICrmFeeApplyService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

/**
 * 费用申请Service业务层处理
 *
 * @author yanwenliang
 * @date 2024-10-28
 */
@Service
public class CrmFeeApplyServiceImpl extends ServiceImpl<CrmFeeApplyMapper, CrmFeeApply> implements ICrmFeeApplyService
{
    @Autowired
    private CrmFeeApplyMapper crmFeeApplyMapper;

    @Autowired
    private ICrmFeeApplyDetailsService crmFeeApplyDetailsService;

    @Autowired
    private ICrmOrderService crmOrderService;

    @Autowired
    private ICrmCustomerService crmCustomerService;


    /**
     * 查询费用申请
     *
     * @param applyId 费用申请主键
     * @return 费用申请
     */
    @Override
    public CrmFeeApply selectCrmFeeApplyByApplyId(String applyId) {
        CrmFeeApply feeApply = crmFeeApplyMapper.selectCrmFeeApplyByApplyId(applyId);
        return feeApply;
    }


    /**
     * 查询费用申请列表
     *
     * @param crmFeeApply 费用申请
     * @return 费用申请
     */
    @Override
    public List<CrmFeeApply> selectCrmFeeApplyList(CrmFeeApply crmFeeApply) {

        if (!SecurityUtils.hasAdmin()){
            crmFeeApply.setUserId(SecurityUtils.getUserId());
//            crmFeeApply.setCreateBy(SecurityUtils.getUsername());
        }

        return crmFeeApplyMapper.selectCrmFeeApplyList(crmFeeApply);
    }

    /**
     * 新增费用申请
     *
     * @param crmFeeApply 费用申请
     * @return 结果
     */
    @Override
    @Transactional
    public int insertCrmFeeApply(CrmFeeApply crmFeeApply) {
        crmFeeApply.setCreateTime(DateUtils.getNowDate());
        crmFeeApply.setCreateBy(SecurityUtils.getUsername());
        crmFeeApply.setApplyId(IdWorker.getIdStr());

        this.buildFeeApplyDetails(crmFeeApply);

        try {
            ThreadLocalUtils.set(FlowTypeEnum.FLOW_FEE_APPLY.getInfo() + ":" + crmFeeApply.getApplyId(), crmFeeApply);
            FlowParamsUtils.start(crmFeeApply, "flow-fee-apply", crmFeeApply.getApplyId());

            return crmFeeApplyMapper.insert(crmFeeApply);
        } finally {
            ThreadLocalUtils.remove(FlowTypeEnum.FLOW_FEE_APPLY.getInfo() + ":" + crmFeeApply.getApplyId());
        }
    }

    /**
     * 构建费用详情
     * @param crmFeeApply
     */
    private void buildFeeApplyDetails(CrmFeeApply crmFeeApply){
        List<CrmFeeApplyDetails> detailList = crmFeeApply.getDetailList();
        if (crmFeeApply.getDetailList().size() < 0){
            throw new ServiceException("请填写至少一条费用明细");
        }

        detailList.forEach(item -> {
            item.setApplyDetailsId(IdWorker.getIdStr());
            item.setApplyId(crmFeeApply.getApplyId());
        });

        crmFeeApplyDetailsService.saveBatch(detailList);
    }

    /**
     * 修改费用申请
     *
     * @param crmFeeApply 费用申请
     * @return 结果
     */
    @Override
    @Transactional
    public int updateCrmFeeApply(CrmFeeApply crmFeeApply) {
        crmFeeApply.setUpdateTime(DateUtils.getNowDate());
        crmFeeApply.setUpdateBy(SecurityUtils.getUsername());

        crmFeeApplyDetailsService.remove(new LambdaQueryWrapper<CrmFeeApplyDetails>()
                .eq(CrmFeeApplyDetails::getApplyId, crmFeeApply.getApplyId()));

        this.buildFeeApplyDetails(crmFeeApply);

        CrmFeeApply feeApply = baseMapper.selectById(crmFeeApply.getApplyId());

        if (AuditStatus.AWAIT_SUBMIT.getCode().equals(feeApply.getAuditStatus())) {
            return crmFeeApplyMapper.updateById(crmFeeApply);
        }

        if (AuditStatus.IN_AUDIT.getCode().equals(feeApply.getAuditStatus())) {
            throw new ServiceException("费用申请审核,无法修改");
        }

        FlowParamsUtils.remove(feeApply.getInstanceId());

        try {
            ThreadLocalUtils.set(FlowTypeEnum.FLOW_FEE_APPLY.getInfo() + ":" + feeApply.getApplyId(), feeApply);
            // 重新开启一个流程
            FlowParamsUtils.start(crmFeeApply, "flow-fee-apply", feeApply.getApplyId());
            crmFeeApply.setAuditStatus(AuditStatus.AWAIT_SUBMIT.getCode());

            return crmFeeApplyMapper.updateById(crmFeeApply);
        } finally {
            ThreadLocalUtils.remove(FlowTypeEnum.FLOW_FEE_APPLY.getInfo() + ":" + crmFeeApply.getApplyId());
        }
    }

    /**
     * 批量删除费用申请
     *
     * @param applyIds 需要删除的费用申请主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteCrmFeeApplyByApplyIds(String[] applyIds) {
        List<CrmFeeApply> crmFeeApplies = crmFeeApplyMapper.selectBatchIds(Arrays.asList(applyIds));
        List<Long> applyIdList = crmFeeApplies.stream().map(CrmFeeApply::getInstanceId).collect(Collectors.toList());
        FlowParamsUtils.remove(applyIdList);
        return crmFeeApplyMapper.deleteBatchIds(Arrays.asList(applyIds));
    }

    /**
     * 删除费用申请信息
     *
     * @param applyId 费用申请主键
     * @return 结果
     */
    @Override
    public int deleteCrmFeeApplyByApplyId(String applyId)
    {
        return crmFeeApplyMapper.deleteById(applyId);
    }

    /**
     * 提交
     * @param crmFeeApply
     * @return
     */
    @Override
    public int submit(CrmFeeApply crmFeeApply) {

        CrmFeeApply feeApply = baseMapper.selectById(crmFeeApply.getApplyId());

        if (ObjectUtils.isEmpty(feeApply)){
            throw new ServiceException("费用申请数据不存在，请刷新后重试");
        }

        try {
            ThreadLocalUtils.set(FlowTypeEnum.FLOW_FEE_APPLY.getInfo() + ":" + feeApply.getApplyId(), feeApply);
            crmFeeApply.setSkipType(SkipType.PASS.getKey());
            FlowParams flowParams = FlowParamsUtils.build(crmFeeApply, "");
            FlowParamsUtils.skipByInsId(crmFeeApply, flowParams);
            crmFeeApply.setAuditStatus(AuditStatus.AWAIT_AUDIT.getCode());
            return baseMapper.updateById(crmFeeApply);
        } finally {
            ThreadLocalUtils.remove(FlowTypeEnum.FLOW_FEE_APPLY.getInfo() + ":" + crmFeeApply.getApplyId());
        }
    }

    /**
     * 撤回提交
     * @param crmFeeApply
     * @return
     */
    @Override
    public int cancelInfo(CrmFeeApply crmFeeApply) {
        CrmFeeApply feeApply = baseMapper.selectById(crmFeeApply.getApplyId());

        if (ObjectUtils.isEmpty(feeApply)){
            throw new ServiceException("费用申请数据不存在，请刷新后重试");
        }

        if (AuditStatus.IN_AUDIT.getCode().equals(feeApply.getAuditStatus())){
            throw new ServiceException("当前费用申请正在审批中，无法撤回");
        }

        FlowParamsUtils.remove(feeApply.getInstanceId());

        FlowParamsUtils.start(crmFeeApply, "flow-fee-apply", feeApply.getApplyId());

        crmFeeApply.setAuditStatus(AuditStatus.AWAIT_SUBMIT.getCode());

        return baseMapper.updateById(crmFeeApply);
    }

    /**
     * 审核
     * @param crmFeeApply
     * @return
     */
    @Override
    public int audit(CrmFeeApply crmFeeApply) {
        CrmFeeApply feeApply = baseMapper.selectById(crmFeeApply.getApplyId());

        if (ObjectUtils.isEmpty(feeApply)){
            throw new ServiceException("费用申请数据不存在，请刷新后重试");
        }


        FlowParams flowParams = FlowParamsUtils.build(crmFeeApply, "");
        Instance instance = FlowParamsUtils.skip(crmFeeApply, flowParams);

        if (instance.getFlowStatus() == 8){
            crmFeeApply.setAuditStatus(flowParams.getSkipType().equals("PASS") ? AuditStatus.PASS.getCode() : AuditStatus.NOT_PASS.getCode());
        } else {
            crmFeeApply.setAuditStatus(AuditStatus.IN_AUDIT.getCode());
        }

        return baseMapper.updateById(crmFeeApply);
    }

    /**
     * 通过商机id和创建人或者归属人查询费用信息
     * @param orderId
     * @return
     */
    @Override
    public List<CrmFeeApply> selectCrmFeeApplyByOrderIdAndCreateBy(String orderId) {
        List<CrmFeeApply> crmFeeApplies = baseMapper.selectList(new LambdaQueryWrapper<CrmFeeApply>()
                .eq(CrmFeeApply::getOrderId, orderId)
                .eq(CrmFeeApply::getUserId, SecurityUtils.getUserId())
                .or()
                .eq(CrmFeeApply::getCreateBy, SecurityUtils.getUsername()));

        return crmFeeApplies;
    }

    @Override
    public FlowDTO conversionObj(Serializable id) {
        CrmFeeApply crmFeeApply = baseMapper.getById(id);
        FlowDTO flowDTO = this.buildFlowDTO(crmFeeApply);
        return flowDTO;
    }

    @Override
    public FlowDTO conversionObjByLocal(Serializable id) {
        CrmFeeApply crmFeeApply = ThreadLocalUtils.get(FlowTypeEnum.FLOW_FEE_APPLY.getInfo() + ":" + id);
        if (!StringUtils.isEmpty(crmFeeApply.getOrderId())){
            CrmOrder crmOrder = crmOrderService.getById(crmFeeApply.getOrderId());
            crmFeeApply.setOrderName(crmOrder.getOrderName());
        } else {
            crmFeeApply.setOrderName("暂未确定");
        }

        if (!StringUtils.isEmpty(crmFeeApply.getCustomerId())){
            CrmCustomer customer = crmCustomerService.getById(crmFeeApply.getCustomerId());
            crmFeeApply.setCustomerName(customer.getCustomerName());
        } else {
            crmFeeApply.setCustomerName("暂未确定");
        }

        FlowDTO flowDTO = this.buildFlowDTO(crmFeeApply);
        return flowDTO;
    }

    private FlowDTO buildFlowDTO( CrmFeeApply crmFeeApply ){
        FlowDTO flowDTO = new FlowDTO(crmFeeApply);
        Map<String, Object> businessValue = flowDTO.getBusinessValue();
        businessValue.put("费用名称", crmFeeApply.getApplyName());
        businessValue.put("费用金额", crmFeeApply.getAmount());
        businessValue.put("商机名称", crmFeeApply.getOrderName());
        businessValue.put("客户名称", crmFeeApply.getCustomerName());
        return flowDTO;
    }
}
